﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace NET.Threads
{
    [TestClass]
    public class Main
    {
        [TestMethod]
        public void TaskTest1()
        {
            Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine(i);
                }
                Console.WriteLine("Task finish");
            });
            Thread.Sleep(200);
            Console.WriteLine("finish");
        }

        [TestMethod]
        public void TaskTest2()
        {
            var t1 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine(i);
                }
                Console.WriteLine("Task finish");
            });
            Thread.Sleep(200);
            Console.WriteLine("finish");
            Task.WaitAll(t1);
        }

        [TestMethod]
        public void TaskTest3()
        {
            var t1 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine(i);
                }
                Console.WriteLine("Task1 finish");
            });
            var t2 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    Thread.Sleep(50);
                    Console.WriteLine((char)('a'+i));
                }
                Console.WriteLine("Task2 finish");
            });
            Task.WaitAll(t1,t2);
        }

        [TestMethod]
        public void TaskTest4()
        {
            var num = 0;
            var t1 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    var tmp = num;
                    Thread.Sleep(30);
                    num = tmp + 1;
                    Console.WriteLine($"Task1 {i} : {num}");
                }
            });
            var t2 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    var tmp = num;
                    Thread.Sleep(20);
                    num = tmp - 1;
                    Console.WriteLine($"Task2 {i} : {num}");
                }
            });
            Task.WaitAll(t1, t2);
            Console.WriteLine($"finish obj:{num}");
        }

        [TestMethod]
        public void TaskTest5()
        {
            var obj = new object();
            var num = 0;
            var t1 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    lock (obj)
                    {
                        var tmp = num;
                        Thread.Sleep(30);
                        num = tmp + 1;
                        Console.WriteLine($"Task1 {i} : {num}");
                    }
                }
            });
            var t2 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    lock (obj)
                    {
                        var tmp = num;
                        Thread.Sleep(20);
                        num = tmp - 1;
                        Console.WriteLine($"Task2 {i} : {num}");
                    }
                }
            });
            Task.WaitAll(t1, t2);
            Console.WriteLine($"finish obj:{num}");
        }

        [TestMethod]
        public void TaskTest6()
        {

            var sema = new Semaphore(1, 1);

            var num = 0;
            var t1 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    sema.WaitOne();
                    var tmp = num;
                    Thread.Sleep(30);
                    num = tmp + 1;
                    Console.WriteLine($"Task1 {i} : {num}");
                    sema.Release();
                }
            });
            var t2 = Task.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    sema.WaitOne();
                    var tmp = num;
                    Thread.Sleep(30);
                    num = tmp - 1;
                    Console.WriteLine($"Task1 {i} : {num}");
                    sema.Release();
                }
            });
            Task.WaitAll(t1, t2);
            Console.WriteLine($"finish obj:{num}");
        }

    }
}
